/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package socof.wget;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 *
 * @author Carlos Pinheiro
 */
public class DownloadersLauncher extends Thread
{
    private static final int WAIT_TIME = 1000;
    private static final int DOWNLOADERS_LIMIT = 10;
    private static final int MAX_BANDWIDTH_ALLOCATION = 800000;
    private ResizeableSemaphore maxDownloaders = new ResizeableSemaphore(0);
    private ExecutorService tpDownloaders = Executors.newCachedThreadPool();
    private static DownloadersLauncher lb = new DownloadersLauncher();
    
    private long maxBandwidthAllocation = MAX_BANDWIDTH_ALLOCATION;
    private int downloadersLimit = DOWNLOADERS_LIMIT;

    private DownloadersLauncher()
    {
    }

    public static DownloadersLauncher getInstance()
    {
        return DownloadersLauncher.lb;
    }

    public void setMaxExecutors(int maxDownloaders)
    {
        this.maxDownloaders.resizeIfRequired(maxDownloaders);
    }
    
    public synchronized void setDownloadersLimit (int downloadersLimit)
    {
        this.downloadersLimit = downloadersLimit;
    }

    @Override
    public void run()
    {
        // Starts bandwith controller
        DownloadersController.getInstance().start();
        
        try
        {
            tpDownloaders = Executors.newCachedThreadPool();
            while (!isInterrupted())
            {
                if (PendingQueue.getInstance().isEmpty())
                {
                    Thread.sleep(WAIT_TIME);
                    continue;
                }
                
                Runnable downloader = new ExecutorDownloader(maxDownloaders);
                tpDownloaders.execute(downloader);               
            }
        }
        catch (InterruptedException ex)
        {            
        }
        finally
        {
            processInterruption();
        }
    }

    private void processInterruption()
    {
        try
        {
            DownloadersController.getInstance().interrupt();
            
            tpDownloaders.shutdown();
            tpDownloaders.awaitTermination(10, TimeUnit.SECONDS);
        } 
        catch (InterruptedException ex)
        {
        }
    }    
    
    /**
     * Allows user to set the max bandwidth allocation
     * @param size 
     */
    public synchronized void setMaxBandwidthAllocation (long size)
    {
        this.maxBandwidthAllocation = size;
    }
    
    public synchronized long getMaxBandwidthAllocation()
    {
        return this.maxBandwidthAllocation;
    }
    
    public void decreaseDownloaders()
    {
        if (maxDownloaders.getTotalPermits() > 1)
            maxDownloaders.removePermit();
    }
    
    public void increaseDownloaders()
    {
        if (maxDownloaders.getTotalPermits() < downloadersLimit)
            maxDownloaders.addPermit();
    }
    
    public void removeAllDownloaders()
    {
        maxDownloaders.removeAllPermits();
    }
    
    public int getNumberOfDownloaders()
    {
        return maxDownloaders.getTotalPermits();
    }
}
